package com.ruoyi.system.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.config.FtpConfig;
import com.ruoyi.common.core.domain.JSONObjectPro;
import com.ruoyi.common.core.page.Page;
import com.ruoyi.common.enums.OrderNameEnum;
import com.ruoyi.common.enums.comlbs.OrderIdValueEnum;
import com.ruoyi.common.enums.comlbs.OrderSendStatusEnum;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DictUtils;
import com.ruoyi.common.utils.SnowFlakeIDGenerator;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.DriverInfo;
import com.ruoyi.system.domain.OrderConfiguration;
import com.ruoyi.system.domain.OrderSendRecord;
import com.ruoyi.system.domain.vo.order.FaceSendInfo;
import com.ruoyi.system.domain.vo.order.OrderConfig;
import com.ruoyi.system.domain.vo.order.OrderSendGroupRecord;
import com.ruoyi.system.mapper.DriverInfoMapper;
import com.ruoyi.system.mapper.OrderConfigurationMapper;
import com.ruoyi.system.mapper.OrderSendRecordMapper;
import com.ruoyi.system.service.IOrderSendRecordService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 指令发送记录Service业务层处理
 * 
 * @author wp
 * @date 2023-08-10
 */
@Service
public class OrderSendRecordServiceImpl extends ServiceImpl<OrderSendRecordMapper, OrderSendRecord> implements IOrderSendRecordService {
    @Autowired
    private OrderSendRecordMapper orderSendRecordMapper;
    @Autowired
    private OrderConfigurationMapper orderConfigurationMapper;
    @Autowired
    private DriverInfoMapper driverInfoMapper;
    @Autowired
    private FtpConfig ftpConfig;

    @DataScope
    @Override
    public List<JSONObject> selectList(OrderSendRecord param) {
        //获取下发记录
        List<OrderSendRecord> recordList = orderSendRecordMapper.list(param);
        //获取指令配置
        Map<Long, OrderConfiguration> orderMap = orderConfigurationMapper.selectList(null)
                .stream().collect(Collectors.toMap(OrderConfiguration::getId, Function.identity()));
        //解析响应结果
        List<JSONObject> resultList = recordList.stream().map(i -> {
            String orderType = i.getOrderType();
            JSONObjectPro item = new JSONObjectPro()
                .put("id", i.getId())
                .put("vehicleNum", i.getVehicleNum())
                .put("status", i.getStatus())
                .put("statusName", DictUtils.getDictLabel("orderSendStatus", i.getStatus()))
                .put("responseTime", DateUtils.parseDateTime(i.getCreateTime()))
                .put("createUserName", i.getCreateUserName())
                .put("failReason", i.getFailReason());
            i.setResponseResult(i.isSendSuccess() ? i.getResponseValue() : "失败");
            item.put("responseResult", i.getResponseResult());
            item.put("orderContent", i.getContent().get("content"));
            //指令内容解析
            OrderConfiguration order = orderMap.get(param.getOrderId());
            Map<String, OrderConfig> propNameMap = order.getConfValue().stream().collect(Collectors.toMap(OrderConfig::getProp, Function.identity()));
            JSONArray items = i.getContent().getJSONArray("items");
            //如果为终端参数设置、开关控制，则需要展示指令内容
            if (OrderNameEnum.SET_PARAMETERS.getCode().equals(orderType)
                    || OrderNameEnum.CONTROL_SWITCH_STATUS.getCode().equals(orderType)) {
                StringBuilder sb = new StringBuilder();
                if (ObjectUtils.isNotEmpty(items)){
                    for (int j = 0; j < items.size(); j++) {
                        JSONObject itemJson = items.getJSONObject(j);
                        OrderConfig config = propNameMap.get(itemJson.getString("id"));
                        if (config != null) {
                            sb.append(config.getName()).append(": ").append(itemJson.getString("value"));
                            if (j < items.size() - 1) sb.append(", ");
                        }
                    }
                }
                item.put("orderContent", sb.toString());
            }
            //如果为位置回传配置，则需要展示指令内容
            if (OrderNameEnum.LOCATION_BACK_SET_PARAMETERS.getCode().equals(orderType)
                    && OrderNameEnum.LOCATION_BACK_SET_PARAMETERS.getText().equals(i.getOrderName())) {
                StringBuilder sb = new StringBuilder();
                if (ObjectUtils.isNotEmpty(items)){
                    for (int j = 0; j < items.size(); j++) {
                        JSONObject itemJson = items.getJSONObject(j);
                        String id = itemJson.getString("id");
                        OrderConfig orderConfig = propNameMap.get(id);
                        if (orderConfig != null) {
                            String name = orderConfig.getName();
                            if (OrderIdValueEnum.LOCATION_REPORT_STRATEGY.getCode().equals(itemJson.getInteger("id"))) {
                                name = OrderIdValueEnum.LOCATION_REPORT_STRATEGY.getText();
                            }
                            if (OrderIdValueEnum.LOCATION_REPORT_SCHEME.getCode().equals(itemJson.getInteger("id"))) {
                                name = OrderIdValueEnum.LOCATION_REPORT_SCHEME.getText();
                            }
                            sb.append(name).append(": ").append(itemJson.getString("value"));
                            if (j < items.size() - 1) sb.append(", ");
                        }
                    }
                }
                item.put("orderContent", sb.toString());
            }
            //如果为超速报警或者疲劳驾驶，则需要展示指令内容
            if (OrderNameEnum.OVER_SPEED_SET_PARAMETERS.getText().equals(i.getOrderName())
                    || OrderNameEnum.TIRED_SET_PARAMETERS.getText().equals(i.getOrderName())) {
                StringBuilder sb = new StringBuilder();
                for (int j = 0; j < items.size(); j++) {
                    JSONObject itemJson = items.getJSONObject(j);
                    String id = itemJson.getString("id");
                    String name = propNameMap.get(id).getName();
                    String value = itemJson.getString("value");
                    String tips = propNameMap.get(id).getTips();
                    //截取备注信息中的单位
                    String unit = tips.substring(3, tips.length() - 1);
                    sb.append(name).append(": ").append(value).append(unit);
                    if (j < items.size() - 1) sb.append(", ");
                }
                item.put("orderContent", sb.toString());
            }
            //查询终端参数指令，应答结果展示返回结果
            if (OrderNameEnum.QUERY_SPECIFIED_PARAMETERS.getCode().equals(orderType)) {
                i.setResponseResult(i.getResponseValue());
                item.put("responseResult", i.getResponseValue());
            }
            //远程升级指令，需要展示升级类型
            if (OrderNameEnum.REMOTE_UPGRADE.getCode().equals(orderType)) {
                String upgradeType = "未知";
                if (i.getContent() != null && i.getContent().get("upgradeType") != null) {
                    upgradeType = DictUtils.getDictLabel("upgradeType", i.getContent().getInteger("upgradeType"));
                }
                item.put("upgradeType", upgradeType);
                item.put("responseResult", StringUtils.isNotEmpty(i.getResponseValue()) ? "版本号：" + i.getResponseValue() : "失败");
            }
            //摄像头立即拍摄指令，需要展示图片和通道号
            if (OrderNameEnum.TAKE_PHOTO_RIGHT_AWAY.getCode().equals(orderType)) {
                if (i.getContent() != null) {
                    item.put("channelId", i.getContent().get("channelId"));
                }
            }
            //终端版本查询指令，应答结果需要展示版本号
            if (OrderNameEnum.DEVICE_VERSION_QUERY.getCode().equals(orderType)) {
                item.put("responseResult", StringUtils.isNotEmpty(i.getResponseValue()) ? "版本号: " + i.getResponseValue() : "失败");
            }
            //人脸识别
            if (OrderNameEnum.DRIVER_FACE.getCode().equals(orderType)) {
                if (StringUtils.isNotEmpty(i.getResponseValue())) {
                    Map<Long, String> driverIdNameMap = driverInfoMapper.list(new DriverInfo()).stream().collect(Collectors.toMap(DriverInfo::getId, DriverInfo::getName));
                    List<String> idWithResult = Arrays.asList(i.getResponseValue().substring(1, i.getResponseValue().length() - 1).split(", "));
                    List<String> result = new ArrayList<>();
                    idWithResult.forEach(d -> {
                        if (StringUtils.isNotEmpty(d)) {
                            String[] split = d.split(":");
                            Long id = Long.parseLong(split[0]);
                            String name = driverIdNameMap.get(id);
                            result.add(name == null ? "未知" : name + ":" + split[1]);
                        }
                    });
                    item.put("responseResult", result.toString());
                } else {
                    item.put("responseResult", "");
                }
            }
            return item;
        }).collect(Collectors.toList());
        return resultList;
    }

    @DataScope
    @Override
    public List<OrderSendRecord> list(OrderSendRecord param) {
        return orderSendRecordMapper.list(param);
    }

    @DataScope
    @Override
    public Page<JSONObject> deviceList(OrderSendRecord param) {
        //获取下发记录
        List<OrderSendRecord> recordList = orderSendRecordMapper.list(param);
        long total = new PageInfo<>(recordList).getTotal();
        //获取指令配置
        List<OrderConfiguration> configurationList = orderConfigurationMapper.selectList(null);
        //解析响应结果
        List<JSONObject> resultList = recordList.stream().map(record -> {
            JSONObjectPro item = new JSONObjectPro()
                    .put("vehicleNum", record.getVehicleNum())
                    .put("orderName", record.getOrderName())
                    .put("status", record.getStatus())
                    .put("statusName", DictUtils.getDictLabel("orderSendStatus", record.getStatus()))
                    .put("responseTime", DateUtils.parseDateTime(record.getCreateTime()))
                    .put("createUserName", record.getCreateUserName())
                    .put("sendTime", DateUtils.parseDateTime(record.getCreateTime()))
                    .put("failReason", record.getFailReason())
                    .put("responseResult", record.isSendSuccess() ? "成功" : "失败")
                    .put("orderContent", record.getContent() == null ? "" : record.getContent().get("content"));
            //如果为超速报警或者疲劳驾驶，则需要展示指令内容
            if (OrderNameEnum.OVER_SPEED_SET_PARAMETERS.getText().equals(record.getOrderName())
                    || OrderNameEnum.TIRED_SET_PARAMETERS.getText().equals(record.getOrderName())){
                Map<Long, OrderConfiguration> configMap = configurationList.stream().collect(Collectors.toMap(OrderConfiguration::getId, Function.identity()));
                List<OrderConfig> configValue = configMap.get(record.getOrderId()).getConfValue();
                //组装数据
                Map<String, String> valueMap = new HashMap<>();
                for (OrderConfig orderConfig : configValue) {
                    valueMap.put(orderConfig.getProp(), orderConfig.getName());
                }
                Map<String, String> tipsMap = new HashMap<>();
                for (OrderConfig orderConfig : configValue) {
                    tipsMap.put(orderConfig.getProp(), orderConfig.getTips());
                }
                JSONArray items = record.getContent().getJSONArray("items");
                StringBuilder sb = new StringBuilder();
                if (items != null && items.size() > 0){
                    for (int j = 0; j < items.size(); j++) {
                        String name = valueMap.get(items.getJSONObject(j).getString("id"));
                        String value = items.getJSONObject(j).get("value").toString();
                        String tips = tipsMap.get(items.getJSONObject(j).getString("id"));
                        String unit = tips.substring(3, tips.length() - 1);
                        sb.append(name).append(":").append(value).append(unit);
                        if (j < items.size() - 1) sb.append(", ");
                    }
                }
                item.put("orderContent", sb.toString());
                item.put("responseResult", record.getStatus() != null && record.isSendSuccess() ? record.getResponseValue() : "失败");
            }
            return item;
        }).collect(Collectors.toList());
        return new Page<>(total, resultList);
    }

    @DataScope
    @Override
    public List<OrderSendGroupRecord> selectGroupList(OrderSendRecord orderSendRecord) {
        return orderSendRecordMapper.groupList(orderSendRecord);
    }

    /**
     * 下发指令
     * @param orderSendRecordList
     */
    public List<JSONObject> add(List<OrderSendRecord> orderSendRecordList){
        //同一组指令记录的groupId相同
        Long groupId = System.currentTimeMillis();
        orderSendRecordList.stream().forEach(i -> {
            JSONObject content = i.getContent();
            if (OrderNameEnum.DRIVER_FACE.getCode().equals(content.get("distributeMsgTopic").toString())) {
                // 人脸识别下发指令(特殊处理)
                List<Long> driverIds = content.getJSONArray("driverIds").toJavaList(Long.class);
                List<DriverInfo> driverInfos = driverInfoMapper.list(new DriverInfo().setIds(driverIds));
                List<FaceSendInfo> faceInfo = new ArrayList<>();
                for (DriverInfo driverInfo : driverInfos) {
                    FaceSendInfo faceSendInfo = new FaceSendInfo();
                    //照片id（司机身份证号）
                    faceSendInfo.setDriverId(driverInfo.getIdCard());
                    //司机名
                    faceSendInfo.setDriverName(driverInfo.getName());
                    //人脸图片地址
                    if (CollectionUtils.isEmpty(driverInfo.getPicture())) continue;
                    faceSendInfo.setFacePictureUrl(ftpConfig.getFacePicUrl() + driverInfo.getPicture().get(0).getPath());
                    faceSendInfo.setFacePictureId(driverInfo.getId().toString());
                    faceSendInfo.setJobSeniorityCard(content.get("jobSeniorityCard").toString());
                    faceSendInfo.setFacePictureAgreement(ftpConfig.getFacePicAgreement());
                    faceSendInfo.setFtpAccount(ftpConfig.getUsername());
                    faceSendInfo.setFtpPassword(ftpConfig.getPassword());
                    faceInfo.add(faceSendInfo);
                }
                content.put("faceInfoList", faceInfo);
                content.remove("driverIds");
                content.remove("jobSeniorityCard");
            } else {
                // 将指令参数为空的数据移除
                List<Map<String, Object>> items = (List) content.getJSONArray("items");
                if (items != null) {
                    items.removeIf(map -> map.get("value") == null || "".equals(map.get("value")));
                    content.put("items", items);
                }
                content.put("devNo", i.getDeviceNo());
                content.put("distributeTime", DateUtils.getTime());
                content.put("requestId", SnowFlakeIDGenerator.getInstance().nextId());
            }
            i.setContent(content).setStatus(OrderSendStatusEnum.WAIT_SEND.getCode()).setGroupId(groupId);
        });
        saveBatch(orderSendRecordList);
        return orderSendRecordList.stream().map(i -> new JSONObjectPro()
                        .put("id", i.getId())
                        .put("content", i.getContent().toJSONString())
        ).collect(Collectors.toList());
    }

    /**
     * 重新下发指令
     * @param orderSendRecordIds
     * @return
     */
    public List<JSONObject> againSendOrder(Long[] orderSendRecordIds){
        //新增指令下发记录
        List<OrderSendRecord> recordList = listByIds(Arrays.asList(orderSendRecordIds));
        Long groupId = System.currentTimeMillis();
        List<OrderSendRecord> newRecordList = recordList.stream().map(i -> {
            OrderSendRecord item = new OrderSendRecord()
                .setOrderId(i.getOrderId())
                .setVehicleId(i.getVehicleId())
                .setVehicleNum(i.getVehicleNum())
                .setDeviceNo(i.getDeviceNo())
                .setContent(i.getContent())
                .setStatus(OrderSendStatusEnum.WAIT_SEND.getCode())
                .setConfValue(i.getConfValue())
                .setGroupId(groupId);
            return item;
        }).collect(Collectors.toList());
        saveBatch(newRecordList);
        return newRecordList.stream().map(i -> new JSONObjectPro()
                .put("id", i.getId())
                .put("content", i.getContent().toJSONString())
        ).collect(Collectors.toList());
    }

}
